//
// GPSMapEdit
// (c) Konstantin Galichsky (kg@geopainting.com), 2002-2007
//
// The Garmin-specific coordinate grid.
//

# include "StdAfx.h"
# include "GarminRound.h"
# include "PtAlgo.h"
# include "Map.h"
# include "fast_floor.h"
# include "Globals.h"

float GarminLatGrid  (const map_t & _map, size_t _cLevelIdx) {
	if (_cLevelIdx >= _map.Levels.size ())
		return 0;
	const size_t cBits = _map.Levels [_cLevelIdx].btBits;
	return 40000000.f/(1UL << cBits);
}

void GarminRoundPoint (const map_t & _map, size_t _cLevelIdx, point_t & _pt) {
	if (! g_bEnableSnapToGrid)
		return;

	if (_cLevelIdx >= _map.Levels.size ())
		return;

	const size_t cBits = _map.Levels [_cLevelIdx].btBits;
	assert (cBits <= 30);
	if (cBits >= 25)
		// NOTE: avoid data damage due to 24-bit mantissa in IEEE32.
		return;

	const float fCell = 360.f/(1UL << cBits);

	_pt.x = fCell*(fast_floor (_pt.x/fCell + .5f));
	_pt.y = fCell*(fast_floor (_pt.y/fCell + .5f));
}

void GarminRoundRect (const map_t & _map, size_t _cLevelIdx, rect_t & _rect) {
	if (! g_bEnableSnapToGrid)
		return;

	if (_cLevelIdx >= _map.Levels.size ())
		return;
	const size_t cBits = _map.Levels [_cLevelIdx].btBits;
	assert (cBits <= 30);
	if (cBits >= 25)
		// NOTE: avoid data damage due to 24-bit mantissa in IEEE32.
		return;

	const float fCell = 360.f/(1UL << cBits);

	_rect.x0 = fCell*(fast_floor (_rect.x0/fCell + .5f));
	_rect.x1 = fCell*(fast_floor (_rect.x1/fCell + .5f));
	_rect.y0 = fCell*(fast_floor (_rect.y0/fCell + .5f));
	_rect.y1 = fCell*(fast_floor (_rect.y1/fCell + .5f));
}

void GarminRoundPoints (const map_t & _map, size_t _cLevelIdx, points_t & _points) {
	if (! g_bEnableSnapToGrid)
		return;

	if (_cLevelIdx >= _map.Levels.size ())
		return;
	const size_t cBits = _map.Levels [_cLevelIdx].btBits;
	assert (cBits <= 30);
	if (cBits >= 25)
		// NOTE: avoid data damage due to 24-bit mantissa in IEEE32.
		return;

	const float fCell = 360.f/(1UL << cBits);
	const float fCellR = 1.f/fCell;

	const size_t cPoints = _points.size ();
	for (size_t cPoint = 0; cPoint < cPoints; ++ cPoint) {
		point_t & pt = _points [cPoint];

		pt.x = fCell*(fast_floor (pt.x*fCellR + .5f));
		pt.y = fCell*(fast_floor (pt.y*fCellR + .5f));
	}
}
